#! /usr/bin/env python

# -*- coding: UTF-8 -*-
# ==============================================================================
# Filename : set_logger.py
# Purpose  : 
# Author   : Yohann Li (lyh001686@sina.com)
# Date     : 2019-11-18 09:53
# ==============================================================================
import logging
from logging import handlers
from os import path, mkdir, makedirs
from datetime import datetime as dt
import functools

project_folder_name = 'LogViewer'
project_folder = path.expanduser(f'~/Library/Application Support/{project_folder_name}')
log_folder = project_folder + '/logs'
record_logger = log_folder + '/app.log'


class Logger():
    """
    1: 设置logger
    2: 检查文件夹是否齐全，避免出现path not found
    """

    def __init__(self):
        self.set_file_folder()
        # self.set_logger()

    def set_logger(self):
        logger = logging.getLogger()
        logger.setLevel(logging.DEBUG)
        # print(f'{self.__class__.__name__}调用一次：handlers:{logger.handlers}')
        if not logger.handlers:
            # print(f'logger {logger.name} have no handlers: {logger.handlers}')
            basic = "%(asctime)s [%(levelname)s %(name)s %(filename)s %(lineno)d %(funcName)s] : %(message)s"
            dt_fmt = "%Y-%m-%d %H:%M:%S"
            fmt = logging.Formatter(fmt=basic, datefmt=dt_fmt)  # 设置logger格式
            # --------- 设置log文件 ----记录上传记录----------
            file_handle_logger = handlers.TimedRotatingFileHandler(record_logger, 'midnight', 1, 365, 'utf8')
            file_handle_logger.setFormatter(fmt)
            file_handle_logger.setLevel(logging.DEBUG)
            # --------- 设置log标准输出 ----------
            stream_handle_logger = logging.StreamHandler()
            stream_handle_logger.setFormatter(fmt)
            stream_handle_logger.setLevel(logging.INFO)
            # --------- 添加logger ----------
            logger.addHandler(file_handle_logger)
            logger.addHandler(stream_handle_logger)
        else:
            # print(f'logger already have handlers: {logger.handlers}')
            pass
        return logger

    def set_file_folder(self):
        """检查文件夹路径是否可用"""
        if not path.exists(project_folder):
            mkdir(project_folder)
        if not path.exists(log_folder):
            mkdir(log_folder)
        with open(record_logger, 'a') as f:
            pass


class GenerateLogger:
    def __init__(self, log_fp=None):
        if log_fp:
            self.set_file_and_folder(log_fp)

    @staticmethod
    def set_file_and_folder(fp):
        parent_folder = path.dirname(fp) if '.' in path.basename(fp) else fp  # 如果basename里包含.则fp为文件路径，否则为文件夹路径
        if not path.exists(parent_folder):
            makedirs(parent_folder)
        if '.' in path.basename(fp):  # 如果fp是文件路径，则创建文件
            with open(fp, 'a') as f:
                pass

    @staticmethod
    def set_logger(name=None, fp=None, sh=None):
        logger = logging.getLogger(name)
        logger.setLevel(logging.DEBUG)
        # print(f'{self.__class__.__name__}调用一次：handlers:{logger.handlers}')
        if not logger.handlers:
            # print(f'logger {logger.name} have no handlers: {logger.handlers}')
            basic = "%(asctime)s [%(levelname)-5s %(name)s %(filename)-20s %(lineno)-3d %(funcName)-17s] : %(message)s"
            dt_fmt = "%Y-%m-%d %H:%M:%S"
            fmt = logging.Formatter(fmt=basic, datefmt=dt_fmt)  # 设置logger格式
            # --------- 设置log文件 ----记录上传记录----------
            if fp:
                file_handle_logger = handlers.TimedRotatingFileHandler(fp, 'midnight', 1, 7, 'utf8')
                file_handle_logger.setFormatter(fmt)
                file_handle_logger.setLevel(logging.DEBUG)
                # --------- 添加logger ----------
                logger.addHandler(file_handle_logger)
            # --------- 如果指定sh，则添加stream handler ----------
            if sh:
                s_h = logging.StreamHandler()
                basic_ = "%(asctime)s | %(filename)-20s %(lineno)-3d %(levelname)-5s %(funcName)-17s | %(message)s"
                dt_fmt_ = "%Y-%m-%d %H:%M:%S"
                fmt_ = logging.Formatter(fmt=basic_, datefmt=dt_fmt_)  # 设置logger格式
                s_h.setFormatter(fmt_)
                # s_h.setFormatter(fmt)
                s_h.setLevel(logging.DEBUG)
                logger.addHandler(s_h)
        else:
            # print(f'logger already have handlers: {logger.handlers}')
            pass

        return logger

    @staticmethod
    def set_stream_logger():
        logger = logging.getLogger()
        logger.setLevel(logging.DEBUG)
        if not logger.handlers:
            # print(f'logger {logger.name} have no handlers: {logger.handlers}')
            basic = "%(name)s %(asctime)s | %(levelname)s %(filename)s %(lineno)d %(funcName)s | : %(message)s"
            dt_fmt = "%Y-%m-%d %H:%M:%S"
            fmt = logging.Formatter(fmt=basic, datefmt=dt_fmt)  # 设置logger格式
            # --------- 添加stream handler ----------
            s_h = logging.StreamHandler()
            s_h.setFormatter(fmt)
            s_h.setLevel(logging.INFO)
            logger.addHandler(s_h)
        else:
            # print(f'logger already have handlers: {logger.handlers}')
            pass
        return logger


def testtime(fun):
    """decorator to test run cycletime"""

    @functools.wraps(fun)
    def runtime(self, *args, **kwargs):
        logger = Logger().set_logger()
        logger.debug(f'Start run {fun.__name__}()')
        start_time = dt.now()
        rts = fun(self, *args, **kwargs)
        stop_time = dt.now()
        cost_seconds = (stop_time - start_time).seconds
        cost_microseconds = (stop_time - start_time).microseconds
        logger.debug(
            f'Run over {fun.__name__ + "()":<25} takes {cost_seconds} seconds, {cost_microseconds} microseconds')
        return rts

    return runtime


def size_strf(size: int):
    if size > 10 ** 9:
        size = f'{size / (10 ** 9):<6.2f} GB'
    elif size > 10 ** 6:
        size = f'{size / (10 ** 6):<6.2f} MB'
    else:
        size = f'{size / (10 ** 3):<6.2f} Bytes'
    return size


FORGROUND_COLOR_PALETTE = dict(black='30;', red='31;', green='32;', yellow='33;', blue='34;', fuchsia='35;', cyan='36;', white='37;')
BACKGROUND_COLOR_PALETTE = dict(black='40', red='41', green='42', yellow='43', blue='44', fuchsia='45', cyan='46', white='47')


def colorize(msg: str, f_color: str = None, b_color: str = None, bold=False, underline=False, flash=False, hide=False,
             show: int = 1):
    _msg = msg
    _f_color = FORGROUND_COLOR_PALETTE.get(f_color, '30;')  # 前景色
    _b_color = BACKGROUND_COLOR_PALETTE.get(b_color, '48')  # 背景色
    _bold = '1;' if bold else ''
    _underline = '4;' if underline else ''
    _flash = '5;' if flash else ''
    _hide = '8;' if hide else ''
    _show = ''.join((_bold, _underline, _flash, _hide))
    _show = ';'.join(str(show)) + ';' if not _show else _show
    msg = f"\033[{_show}{_f_color}{_b_color}m{_msg}\033[0m"
    return msg


if __name__ == '__main__':
    pass
